<template>
  <div class="flex flex-col h-full"> <!-- 根容器 -->
  <header class="bg-white p-2 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 m-4">
    <div class="container mx-auto flex justify-between items-center">
      <div class="flex items-center space-x-3">
        <i class="fa fa-exchange text-primary text-2xl"></i>
        <h1 class="text-xl font-bold text-gray-800">
          <div class="bg-gradient-to-r from-blue-500 to-indigo-600 text-white p-3 rounded-t-lg font-semibold text-base">
            ZQ Log & OTA Tools
          </div>
        </h1>
      </div>

      <div class="flex items-center space-x-4">
        <div class="text-sm text-gray-600 flex items-center">
          <i class="fa fa-server mr-2"></i>
          <span id="server-status" class="font-medium text-green-500">已连接</span>
        </div>
        <button id="refresh-btn" class="btn-secondary flex items-center px-3 py-1.5 text-sm bg-gray-200 hover:bg-gray-300 rounded transition-colors">
          <i class="fa fa-refresh mr-1"></i> 刷新
        </button>
      </div>
    </div>
  </header>

  <main class="h-full flex overflow-hidden w-full flex-1 bg-gray-50">
    <!-- M0日志通道 -->
    <!-- <div class="flex-[5] bg-white p-4 border-r border-gray-200 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 m-4 h-full flex flex-col"> -->
    <div class="flex-[5] bg-white p-4 border-r border-gray-200 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 m-4 h-full flex flex-col overflow-hidden min-h-0">
      <h2 class="font-semibold text-lg mb-2 flex justify-between items-center text-gray-800 shrink-0">
        <span>M0日志通道</span>
        <div class="flex space-x-2">
          <button @click="copyLog('log1')" class="text-xs px-2 py-1 bg-blue-100 text-blue-700 hover:bg-blue-200 rounded transition-colors">
            <i class="fa fa-copy mr-1"></i>复制
          </button>
          <button @click="saveLog('log1')" class="text-xs px-2 py-1 bg-green-100 text-green-700 hover:bg-green-200 rounded transition-colors">
            <i class="fa fa-save mr-1"></i>保存
          </button>
          <button @click="clearLog('log1')" class="text-xs px-2 py-1 bg-gray-200 hover:bg-gray-300 rounded transition-colors">
            <i class="fa fa-trash-o mr-1"></i>清空
          </button>
          <button @click="toggleAutoScroll('log1')" class="text-xs px-2 py-1 bg-gray-200 hover:bg-gray-300 rounded transition-colors">
            <i class="fa fa-lock mr-1"></i>{{ log1AutoScroll ? '锁定' : '解锁' }}
          </button>
        </div>
      </h2>

      <div class="border border-gray-200 rounded-lg flex-1 flex flex-col overflow-hidden min-h-0">
        <div class="flex-1 overflow-y-auto p-3 "  ref="log1Container">
          <!-- <div v-for="(entry, index) in log1Entries" :key="index" class="mb-1 text-sm break-words whitespace-pre-wrap"> -->
          <div v-for="(entry, index) in log1Entries" :key="index" class="mb-1 text-sm break-all whitespace-normal">
            {{ entry }}
          </div>
        </div>
      </div>
    </div>

    <!-- Cat1日志通道 -->
    <!-- <div class="flex-[5] bg-white p-4 border-r border-gray-200 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 m-4 h-full flex flex-col"> -->
    <div class="flex-[5] bg-white p-4 border-r border-gray-200 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 m-4 h-full flex flex-col overflow-hidden min-h-0">
      <h2 class="font-semibold text-lg mb-2 flex justify-between items-center text-gray-800 shrink-0">
        <span>Cat1日志通道</span>
        <div class="flex space-x-2">
          <button @click="copyLog('log2')" class="text-xs px-2 py-1 bg-blue-100 text-blue-700 hover:bg-blue-200 rounded transition-colors">
            <i class="fa fa-copy mr-1"></i>复制
          </button>
          <button @click="saveLog('log2')" class="text-xs px-2 py-1 bg-green-100 text-green-700 hover:bg-green-200 rounded transition-colors">
            <i class="fa fa-save mr-1"></i>保存
          </button>
          <button @click="clearLog('log2')" class="text-xs px-2 py-1 bg-gray-200 hover:bg-gray-300 rounded transition-colors">
            <i class="fa fa-trash-o mr-1"></i>清空
          </button>
          <button @click="toggleAutoScroll('log2')" class="text-xs px-2 py-1 bg-gray-200 hover:bg-gray-300 rounded transition-colors">
            <i class="fa fa-lock mr-1"></i>{{ log2AutoScroll ? '锁定' : '解锁' }}
          </button>
        </div>
      </h2>

      <div class="border border-gray-200 rounded-lg flex-1 flex flex-col overflow-hidden min-h-0">
        <div class="flex-1 overflow-y-auto p-3 "  ref="log2Container">
          <!-- <div v-for="(entry, index) in log2Entries" :key="index" class="mb-1 text-sm break-words whitespace-pre-wrap"> -->
          <div v-for="(entry, index) in log2Entries" :key="index" class="mb-1 text-sm break-all whitespace-normal">
            {{ entry }}
          </div>
        </div>
      </div>
    </div>

    <!-- 右侧操作区域 -->
    <div class="flex-[2] bg-white p-4 border-l border-gray-200 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 m-4">

      <!-- 设备选择区域 -->
      <div>
        <div class="flex justify-between items-center mb-4">
          <div class="text-xl font-semibold text-blue-600 self-center">选择设备</div>
        </div>

          <!-- @change="SelectDev"  -->
        <input 
          v-model="SelectedDev" 
          list="serialPortsList"
          class="w-full p-2 border border-gray-300 rounded-md"
          autocomplete="off"
        />
        <datalist id="serialPortsList">
          <option v-for="(v, i) in DevList" :key="i" :value="v">{{ v }}</option>
        </datalist>


        <p v-if="serialPortStatus" class="mt-2 text-sm" :class="serialPortSuccess ? 'text-green-600' : 'text-red-600'">
          {{ serialPortMessage }}
        </p>

        <div class="flex justify-between items-center mt-6 mb-4">
          <!-- 刷新按钮 -->
          <button @click="RefreshDevice" :disabled="IsDevRefresh" class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-2 rounded-md transition-all duration-200">
              {{ IsDevRefresh ? '刷新中...' : '刷新设备' }}
          </button>
          <!-- 启动/停止按钮 -->
          <button @click="ToggleDevice" class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-2 rounded-md transition-all duration-200">
            <!-- 动态图标 -->
            <i class="fas mr-1" :class="IsDevRunning ? 'fa-unlink' : 'fa-plug'" :style="{ color: IsDevRunning ? '#ef4444' : '#10b981' }"></i>            
            {{ IsDevRunning ? '断开' : '连接' }}
          </button>
        </div>

        <!-- 进度条 -->
        <div v-if="IsDevRefresh" class="w-full mt-2 bg-gray-300 rounded-full h-1">
          <div 
            class="bg-blue-600 h-1 rounded-full transition-all duration-1000 ease-linear" 
            :style="{ width: DevRefreshProgress + '%' }">
          </div>
        </div>

      </div>
      
      <!-- 新增分隔线 -->
      <div class="border-t border-gray-300 my-6"></div>
      <!-- OTA升级 -->
      <div class="flex justify-between items-center mb-4">
        <div class="text-xl font-semibold text-blue-600 self-center">上传HEX文件</div>
        <!-- 传统上传按钮 -->
        <label for="fileUpload" class="inline-flex items-center px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white font-medium rounded-md cursor-pointer transition-colors">
          <i class="fa fa-folder-open mr-2"></i>选择文件
        </label>
      </div>
      <div class="border-2 border-dashed border-gray-400 rounded-lg p-8 text-center transition-all duration-300 hover:border-blue-500" @dragover.prevent="() => {}" @drop.prevent="handleDrop">
        <input type="file" id="fileUpload" accept=".img, .bin, .cat" class="hidden" @change="handleFileUploadAndReset"/>
        <label for="fileUpload" class="cursor-pointer block">
          <i class="fa fa-cloud-upload text-4xl text-blue-500 mb-2"></i>
          <p class="text-gray-700">点击或拖拽OTA文件到此处上传</p>
          <p class="text-sm text-gray-500 mt-1">支持单个img/bin/cat文件，最大10MB</p>
        </label>
      </div>
      <!-- 上传状态 -->
      <div v-if="uploadStatus" class="mt-4 p-3 rounded-md text-sm" :class="uploadSuccess ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'">
        {{ uploadMessage }}
      </div>
  
    </div>
  </main>
  </div>
</template>
<script>
import io from 'socket.io-client';

export default {
  name: 'App',
  data() {
    return {
      IsDevRefresh: false,
      DevRefreshProgress: 0,
      progressInterval: null,

      socket: null,
      log1Entries: [],
      log2Entries: [],
      log1AutoScroll: true,
      log2AutoScroll: true,
      uploadStatus: false,
      uploadSuccess: false,
      uploadMessage: '',

      DevList: [],
      SelectedDev: '',
      IsDevRunning:false,

      serialPorts: [],
      serialPortStatus: false,
      serialPortSuccess: false,
      serialPortMessage: '',
      
      ble_devs: [],
      selected_ble_status: false,
      selected_ble_success: false,
    };
  },
  mounted() {
    this.socket = io('http://localhost:5000');
    
    this.socket.on('log1', (data) => {
      this.addLogEntry('log1', data.data);
    });
    
    this.socket.on('log2', (data) => {
      this.addLogEntry('log2', data.data);
    });
    
    this.socket.on('connect', () => {
      this.addLogEntry('log1', '已连接到服务器');
    });
    
    this.socket.on('disconnect', () => {
      this.addLogEntry('log1', '与服务器的连接已断开');
    });

  },
  methods: {
      async RefreshDevice() {
        if (this.IsDevRefresh) return;

        this.IsDevRefresh = true;
        this.DevRefreshProgress = 0;

        // 通知后台刷新串口和ble设备列表
        this.DevList = [];
        this.RefreshSerialList();
        this.RefreshBleList();
        
        // 进度总时间 6s
        const duration = 6000; 
        const step = 100 / (duration / 100); // 每 100ms 更新一次进度
        this.progressInterval = setInterval(() => {
          this.DevRefreshProgress += step;
          if (this.DevRefreshProgress >= 100) {
            clearInterval(this.progressInterval);
            this.DevRefreshProgress = 100;
            this.IsDevRefresh = false;
          }
        }, 100);

      },
    // beforeUnmount() {
    //   if (this.progressInterval) {
    //     clearInterval(this.progressInterval);
    //   }
    // },
    
    handleDrop(event) {
      const file = event.dataTransfer.files[0];
      if (file) {
        this.handleFileUploadAndReset({ target: { files: [file] } });
      }
    },
    // ...其他方法保持不变
    handleFileUploadAndReset(event) {
      const file = event.target.files[0];
      if (!file) return;
      
      if (!file.name.endsWith('.img') && !file.name.endsWith('.bin') && !file.name.endsWith('.cat')) {
        this.showUploadStatus(false, '请选择img/bin/cat格式的文件');
        return;
      }
      
      this.showUploadStatus(true, '正在上传文件...', false);
      
      const formData = new FormData();
      formData.append('file', file);
      
      fetch('http://localhost:5000/upload', {
        method: 'POST',
        body: formData
      })
      .then(response => response.json())
      .then(data => {
        if (data.error) {
          this.showUploadStatus(false, data.error);
        } else {
          this.showUploadStatus(true, data.message);
        }
      })
      .catch(error => {
        this.showUploadStatus(false, '上传失败: ' + error.message);
      });

      event.target.value = null;
    },
    
    showUploadStatus(success, message, autoHide = true) {
      this.uploadSuccess = success;
      this.uploadMessage = message;
      this.uploadStatus = true;
      
      if (autoHide) {
        setTimeout(() => {
          this.uploadStatus = false;
        }, 5000);
      }
    },
    
    addLogEntry(logType, message) {
      const now = new Date();
      const timestamp = now.toLocaleTimeString();
      // 按换行符分割消息
      const messages = message.split('\n');

      const logEntry = `[${timestamp}] ${message}`;
      
      if (logType === 'log1') {
        // 为每个消息添加时间戳并推送到数组
        messages.forEach(msg => {
          // if (!msg.endsWith('\n')) msg += '\n';
          if (msg === '' || msg === '\n') return;
          const logEntry = `[${timestamp}] ${msg}`;
          this.log1Entries.push(logEntry);
          if (this.log1Entries.length > 1000*1000) {
            this.log1Entries.shift();
          }
        });
        this.$nextTick(() => {
          this.scrollToBottom('log1');
        });
      } else {
        // 为每个消息添加时间戳并推送到数组
        messages.forEach(msg => {
          if (msg === '' || msg === '\n') return;
          const logEntry = `[${timestamp}] ${msg}`;
          this.log2Entries.push(logEntry);
          if (this.log2Entries.length > 1000*1000) {
            this.log2Entries.shift();
          }
        });
        this.$nextTick(() => {
          this.scrollToBottom('log2');
        });
      }
    },
    
    scrollToBottom(logType) {
      if ((logType === 'log1' && this.log1AutoScroll) || (logType === 'log2' && this.log2AutoScroll)) {
        const container = this.$refs[`${logType}Container`];
        if (container) {
          container.scrollTop = container.scrollHeight;
        }
      }
    },
    
    clearLog(logType) {
      if (logType === 'log1') {
        this.log1Entries = [];
      } else {
        this.log2Entries = [];
      }
    },
    
    toggleAutoScroll(logType) {
      if (logType === 'log1') {
        this.log1AutoScroll = !this.log1AutoScroll;
      } else {
        this.log2AutoScroll = !this.log2AutoScroll;
      }
    },

    async copyLog(logType) {
      let logs = logType === 'log1' ? this.log1Entries.join('\n') : this.log2Entries.join('\n');
      try {
        await navigator.clipboard.writeText(logs);
        alert('已复制到剪贴板');
      } catch (err) {
        alert('复制失败: ' + err.message);
      }
    },
    
    saveLog(logType) {
      const timestamp = new Date().toISOString().replace(/[^0-9]/g, '').slice(0, 14);
      const filename = `${logType}_${timestamp}.log`;
      let content = logType === 'log1' ? this.log1Entries.join('\n') : this.log2Entries.join('\n');

      const blob = new Blob([content], { type: 'text/plain' });
      const url = URL.createObjectURL(blob);

      const a = document.createElement('a');
      a.href = url;
      a.download = filename;
      a.click();
      URL.revokeObjectURL(url);
    },

    // 串口相关方法
    async RefreshSerialList() 
    {
      try {
        const response = await fetch('http://localhost:5000/ports');
        const data = await response.json();
        for (let i = 0; i < data.ports.length; i++) {
          this.DevList.push(data.ports[i][0]+" - "+data.ports[i][1]);
        }
      } catch (error) {
        console.error('无法刷新串口列表:', error);
      }
    },

    ToggleDevice() {
      this.IsDevRunning = !this.IsDevRunning;
      fetch('http://localhost:5000/toggle-device', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({
          start: this.IsDevRunning,
          dev: this.SelectedDev.split('-')[0].trim()
        })
      })
      .then(response => response.json())
      .then(data => {
        if (data.error) {
          this.showSerialPortStatus(false, data.error);
        } else {
          this.showSerialPortStatus(true, data.message);
        }
      })
      .catch(error => {
        this.showSerialPortStatus(false, '选择串口失败: ' + error.message);
      });
    },



    showSerialPortStatus(success, message) {
      this.serialPortSuccess = success;
      this.serialPortMessage = message;
      this.serialPortStatus = true;

      setTimeout(() => {
        this.serialPortStatus = false;
      }, 5000);    
    },


    
    // BLE相关方法
    async RefreshBleList() 
    {
      try {
        const response = await fetch('http://localhost:5000/ble_devs');
        const data = await response.json();
    
        for (let i = 0; i < data.devs.length; i++) {
          this.DevList.push(data.devs[i][0]+" - "+data.devs[i][1]+" - ("+data.devs[i][2]+")");
        }
        
      } catch (error) {
        console.error('无法刷新BLE列表:', error);
      }
    },    
    
  }
};

</script>

